Typical HAL DMA use cases for migration

This section presents the typical DMA use cases for migration from HAL1 to HAL2.

Note

  • For some STM32 series: The multiplier is 1 because HAL APIs work with bytes.

  • For other STM32 series: The multiplier depends on the source data size since HAL APIs work with beats (same as the source data width). Users need to adjust the data size by multiplying it by the multiplier according to the source data size. For example, if the source data size is a word, the data size needs to be multiplied by 4.

Use case: DMA channel direct mode transfer in polling mode

Sequence diagram

DMA channel direct mode transfer in polling mode.

  @startuml
  hide footbox
  participant "User Application" as part1
  participant "DMA Driver"       as part3

  group Configuration
  part1->part3 : HAL_DMA_Init()
  end

  group Process
      group  Start
          part1->part3 : HAL_DMA_Start()
      end
      group  Polling for transfer
          part1->part3 : HAL_DMA_PollForTransfer()
          part3->part1:
      end
  end

  @enduml

Code snippet

HAL1

HAL2

HAL_DMA_Init(&hdma1);


HAL_DMA_Start(&hdma, (uint32_t)srcAddress, (uint32_t)dstAddress
                                                 , dataSize);

HAL_DMA_PollForTransfer(&hdma, HAL_DMA_FULL_TRANSFER, timeout);
HAL_DMA_Init(&hdma1, GPDMA1_CH0);
HAL_DMA_SetConfigDirectXfer(&hdma1, directXferConfig);

HAL_DMA_StartDirectXfer(&hdma, (uint32_t)srcAddress, (uint32_t)dstAddress
                                                     , dataSize * multiplier);

HAL_DMA_PollForXfer(&hdma, HAL_DMA_XFER_FULL_COMPLETE, timeout);

Key changes

  1. HAL2 requires explicit direct-transfer configuration using HAL_DMA_SetConfigDirectXfer() (or HAL_DMA_SetConfigPeriphDirectXfer()).

  2. HAL2 starts transfers using HAL_DMA_StartDirectXfer() and polls using HAL_DMA_PollForXfer().

  3. Depending on the series, the transfer size may need to be expressed in bytes or beats (see the note in the main DMA use-cases page).


Use case: DMA channel direct mode transfer in interrupt mode

Sequence diagram

DMA channel direct mode transfer in interrupt mode.

  @startuml
  hide footbox
  participant "User Application" as part1
  participant "DMA Driver"       as part3
  participant "NVIC"             as part4

  group Configuration
  part1->part3 : HAL_DMA_Init()
  end

  group Process
      group  Start
          part1->part3 : HAL_DMA_Start_IT()
      end

      group  Interrupt
          part4->part3 : HAL_DMA_IRQHandler()
          part3->part1 : User callback()
      end
  end

  @enduml

Code snippet

HAL1

HAL2

HAL_DMA_Init(&hdma);


HAL_DMA_Start_IT(&hdma, (uint32_t)srcBuffer, (uint32_t)destBuffer, dataSize);
HAL_DMA_Init(&hdma1, GPDMA1_CH0);
HAL_DMA_SetConfigDirectXfer(&hdma, &directXferConfig);

HAL_DMA_StartDirectXfer_IT(&hdma, (uint32_t)srcBuffer, (uint32_t)destBuffer, dataSize * multiplier);

Key changes

  1. HAL2 starts interrupt-driven direct transfers using HAL_DMA_StartDirectXfer_IT() (or the optimized variant).

  2. HAL2 uses HAL_DMA_SetConfigDirectXfer() to configure the transfer before starting it.

  3. The DMA interrupt handler remains HAL_DMA_IRQHandler().


Use case: DMA channel linear linked-list mode transfer in polling mode

Note

To perform a DMA linked-list transfer, follow these steps:

  • First, fill the desired nodes with the required configuration.

  • Next, create a queue using these filled nodes.

  • Finally, start the transfer using the built queue.

Sequence diagram

Linked-list mode transfer in polling mode.

  @startuml
  hide footbox
  participant "User Application" as part1
  participant "DMA Driver"       as part3

  group Configuration
  part1->part3 : HAL_DMAEx_List_BuildNode()
  part1->part3 : HAL_DMAEx_List_InsertNode()
  part1->part3 : HAL_DMAEx_List_Init()
  end

  group Process
      group  Start
          part1->part3 : HAL_DMAEx_List_Start()
      end
      group  Polling for transfer
          part1->part3 : HAL_DMA_PollForTransfer()
          part3->part1:
      end
  end

  @enduml

Code snippet

HAL1

HAL2

HAL_DMAEx_List_BuildNode(&NodeConf, &Node1);

HAL_DMAEx_List_InsertNode(&Queue1, NULL, &Node1);


HAL_DMAEx_List_Init(&LL_HandleDMA1);


HAL_DMAEx_List_LinkQ(&LL_HandleDMA1, &Queue1);

HAL_DMAEx_List_Start(&LL_HandleDMA1)


HAL_DMA_PollForTransfer(&hdma_F, HAL_DMA_FULL_TRANSFER, timeout);
HAL_DMA_FillNodeConfig(Node1, NodeConf, HAL_DMA_NODE_2D_ADDRESSING);

HAL_Q_Init(Queue2, &HAL_DMA_2DAddressing_DescOps);
HAL_Q_InsertNode(Queue2, NULL, Node1);

HAL_DMA_Init(LL_DMA_Handle1, HAL_GPDMA1_CH12);
HAL_DMA_SetConfigLinkedListXfer(LL_DMA_Handle1, LL_xfer_config1);



HAL_DMA_StartLinkedListXfer(&hdma, srcAddress, dstAddress, dataSize * multiplier);


HAL_DMA_PollForXfer(&hdma, HAL_DMA_XFER_FULL_COMPLETE, timeout);

Key changes

  1. HAL2 introduces a queue-based approach using HAL_Q_* services for linked-list transfers.

  2. HAL2 configures linked-list transfers using HAL_DMA_SetConfigLinkedListXfer() and starts them using HAL_DMA_StartLinkedListXfer().

  3. HAL2 uses HAL_DMA_PollForXfer() for polling completion.


Use case: DMA channel linear linked-list mode transfer in interrupt mode

Sequence diagram

Linked-list mode transfer in interrupt mode.

  @startuml
  hide footbox
  participant "User Application" as part1
  participant "DMA Driver"       as part3
  participant "NVIC"             as part4

  group Configuration
  part1->part3 : HAL_DMAEx_List_BuildNode()
  part1->part3 : HAL_DMAEx_List_InsertNode()
  part1->part3 : HAL_DMAEx_List_Init()
  end

  group Process
      group  Start
          part1->part3 : HAL_DMAEx_List_Start_IT()
      end
      group  Interrupt
          part4->part3 : HAL_DMA_IRQHandler()
          part3->part1 : User callback()
      end
  end

  @enduml

Code snippet

HAL1

HAL2

HAL_DMAEx_List_BuildNode(&NodeConf, &Node1);

HAL_DMAEx_List_InsertNode(&Queue2, NULL, &Node1);


HAL_DMAEx_List_Init(&LL_HandleDMA1);


HAL_DMAEx_List_LinkQ(&LL_HandleDMA1, &Queue2);

HAL_DMAEx_List_Start_IT(&LL_HandleDMA1)
HAL_DMA_FillNodeConfig(Node1, NodeConf, HAL_DMA_NODE_2D_ADDRESSING);

HAL_Q_Init(Queue2, &HAL_DMA_2DAddressing_DescOps);
HAL_Q_InsertNode(Queue2, NULL, Node1);

HAL_DMA_Init(LL_DMA_Handle1, HAL_GPDMA1_CH12);
HAL_DMA_SetConfigLinkedListXfer(LL_DMA_Handle1, LL_xfer_config1);



HAL_DMA_StartLinkedListXfer_IT(LL_DMA_Handle1, Queue2);

Key changes

  1. HAL2 supports interrupt-driven linked-list transfers through HAL_DMA_StartLinkedListXfer_IT().

  2. HAL2 uses a queue-based approach for building and inserting nodes.

  3. The DMA interrupt handler remains HAL_DMA_IRQHandler().


Use case: DMA channel peripheral transfer in circular mode

Sequence diagram

Peripheral transfer in circular mode.

  @startuml
  hide footbox
  participant "User Application" as part1
  participant "PPP Driver"       as part4
  participant "DMA Driver"       as part3
  participant "NVIC"             as part5

  group Configuration
  part1->part3 : HAL_DMA_Init()
  part1->part3 : HAL_DMAEx_List_Init()
  end

  group Process
      group  Start
          part1->part4 : **Start PPP DMA process**
      end

      group  Repeated until PPP stop DMA
          part4->part3 : HAL_DMAEx_List_Start_IT()
          part5->part3 : HAL_DMA_IRQHandler()
          part3->part4 : PPP DMA transfer callback
          part4->part1 : <b>User PPP process callback
      end
      part1->part4 : **Stop PPP DMA process**
      part4->part3 : HAL_DMA_Abort_IT()
      part3->part4 : HAL_DMA_RegisterCallback(AbortCallback)
      part4->part1 : User callback()
  end

  @enduml

Note

The DMA start and stop procedures must be adjusted according to the selected peripheral (PPP).

Code snippet

The following code snippet is an example of I2C DMA transfer in circular mode.

HAL1

HAL2

HAL_DMA_Init(&handle_GPDMA1_Channe0);
HAL_DMAEx_List_Init(&handle_GPDMA1_Channe0);
HAL_DMA_Init(&hdma1, GPDMA1_CH0);
HAL_DMA_SetConfigPeriphLinkedListCircularXfer(&hdma1, &DMA_Node_I2C1_TX, &xfer_cfg_i2c1_tx_dma);

Key changes

  1. HAL2 configures circular peripheral transfers using HAL_DMA_SetConfigPeriphLinkedListCircularXfer().

  2. HAL2 starts the peripheral transfer using HAL_DMA_StartPeriphXfer_IT_Opt().

  3. Abort and IRQ handling remain based on HAL_DMA_Abort_IT() and HAL_DMA_IRQHandler().